<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>FLIP动画</title>
    <style>
        body {
            margin: 0;
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-items: center;
            padding-top: 100px;
        }

        .container {
            padding: 20px 30px;
            border: 1px #ffc2c2 solid;
            border-radius: 5px;
            width: 200px;
            margin-top: 20px;
            height: 400px;
            display: grid;
            grid-template-columns: repeat(1, 1fr);
            gap: 20px;
        }

        .box {
            padding: 10px 20px;
            border-radius: 20px;
            background-color: #36d3a9;
            color: #fff;
            box-sizing: border-box;
            width: 100%;
            text-align: left;
            border: #36e4da 2px solid;
        }

        .active {
            background: #ef4444;
        }
    </style>
</head>
<body>
<button id="btn">改变第一个元素的位置</button>
<div class="container">
    <div class="box active first">HTML + CSS</div>
    <div class="box">网络</div>
    <div class="box">工程</div>
    <div class="box">框架</div>
    <div class="box">移动端</div>
    <div class="box">Node JS</div>
</div>

<script>
    const btn = document.getElementById('btn');
    const container = document.querySelector('.container');


    function getLocation() {
        const first = document.querySelector('.first')
        const rect = first.getBoundingClientRect();
        return rect.top
    }

    btn.addEventListener('click', () => {
        const first = document.querySelector('.first')
        const boxs = document.querySelectorAll('.box');

        // 清除之前的transform和transition
        first.style.transition = 'none';
        first.style.transform = 'none';

        // 强制重绘，确保样式已应用
        first.getBoundingClientRect();

        // 获取第一个元素开始的位置
        const start = getLocation()
        // 将第一个元素放到最后的位置
        container.removeChild(first)
        container.insertBefore(first, boxs.item(boxs.length))
        // 获取第一个元素结束的位置
        const end = getLocation()
        // 移除第一个元素的active类
        boxs.item(0).classList.remove('active', 'first');
        const dis = start - end
        first.style.transform = `translateY(${dis}px)`
        boxs.item(1).classList.add('active', 'first');
        raf(() => {
            first.style.transition = 'transform 1s'
            first.style.removeProperty('transform')
        })
    })

    function raf(callback) {
        requestAnimationFrame(() => {
            requestAnimationFrame(callback)
        })
    }
</script>
</body>
</html>